﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CloudPms.Common.CacheInterface;
using CloudPms.Common.Utils;
using CloudPms.Entity.Entities;
using ServiceStack.Common.Extensions;
using ServiceStack.Redis;
using ServiceStack.Redis.Generic;

namespace CloudPms.Common.CacheProvider
{
    /// <summary>
    /// 房间信息缓存存储与更新服务
    /// <para>--------------------------</para>
    /// <para>@Author: cnalexi@gmail.com</para> 
    /// <para>@Create: 2012/10/06</para>  
    /// <example>
    /// <code>
    /// var rcStore = container.Resolve[IRoomCacheStore>();//container是UnityIOC容器
    /// </code>
    /// </example> 
    /// </summary>
    public class RoomCacheStore : IRoomCacheStore
    {
        private PooledManager pm = PooledManager.Instance;

        private const string RoomCacheKey = "urn:Room:";

        public string GetCacheKey(string tags)
        {
            return RoomCacheKey + tags;
        }

        /// <summary>
        /// 批量添加房间进缓存
        /// </summary>
        /// <param name="hotelId"></param>
        /// <param name="hotelRooms"></param>
        public void BatchSet(string hotelId, IEnumerable<Room> hotelRooms)
        {
            if (string.IsNullOrWhiteSpace(hotelId) || hotelRooms == null || !hotelRooms.Any())
                throw new ArgumentNullException(ErrorCode.CACHE_ADD_NO_DATA);

            string key = GetCacheKey(hotelId);

            DateTime timestamp = hotelRooms.Max(r => r.ModifiedTime);

            var roomCacheTime = new RoomCacheTime {HotelID = hotelId, Timestamp = timestamp};

            using (var client = pm.GetPooledClientManager(hotelId).GetClient())
            {
                var roomClient = client.GetTypedClient<Room>();

                using (var trans = roomClient.CreateTransaction())
                {
                    trans.QueueCommand(c =>
                    {
                        hotelRooms.ForEach(r =>
                        {
                            string roomKey = r.HotelID + r.RoomNo;

                            if (c.ContainsKey(roomKey))
                            {
                                if (c.RemoveEntry(roomKey))
                                {
                                    c.SetEntry(r.HotelID + r.RoomNo, r);
                                }
                            }
                            else
                            {
                                c.SetEntry(r.HotelID + r.RoomNo, r);
                            }
                        });
                    });

                    trans.Commit();
                }

                UpdateCacheTime(hotelId,roomCacheTime);

                var rooms = roomClient.GetValues(hotelRooms.Select(r => r.HotelID + r.RoomNo).ToList());
                
                var hotel = roomClient.Lists[key];
                
                hotel.AddRange(rooms);
            }
        }

        public IList<Room> BatchGet(string hotelId)
        {
            string key = GetCacheKey(hotelId);

            using (var client = pm.GetPooledClientManager(hotelId).GetClient())
            {
                var roomClient = client.GetTypedClient<Room>();

                var roomList = roomClient.Lists[key];

                return roomList.GetAll();
            }
        }

        public IList<Room> BatchGet(string hotelId, DateTime modifiedTime)
        {
            if (string.IsNullOrWhiteSpace(hotelId))
                throw new ArgumentNullException(ErrorCode.CACHE_GET_NULL_ARGUMENT+"酒店编号");

            string key = GetCacheKey(hotelId);

            using (var client = pm.GetPooledClientManager(hotelId).GetClient())
            {
                var roomClient = client.GetTypedClient<Room>();

                var roomList = roomClient.Lists[key];

                //lastTime 房间更新的时间 取select gettime()数据库时间为准

                var rooms= roomList.Where(r => r.ModifiedTime > modifiedTime).ToList();

                return rooms;
            }


        }
        
        public Room Get(string hotelId,string roomNo)
        {
            if (string.IsNullOrWhiteSpace(hotelId) || string.IsNullOrWhiteSpace(roomNo))
                throw new ArgumentNullException("获取房间缓存时酒店编号和房号不允许为空");

            using (var client = pm.GetPooledClientManager(hotelId).GetClient())
            {
                var roomClient = client.GetTypedClient<Room>();

                return roomClient.GetValue(hotelId + roomNo);
            }
        }

        private void UpdateCacheTime(string hotelId,RoomCacheTime cacheTime)
        {
            string key = GetCacheKey("Time:" + cacheTime.HotelID);

            using (var client = pm.GetPooledClientManager(hotelId).GetClient())
            {
                var cacheTimeClient = client.GetTypedClient<RoomCacheTime>();

                if (cacheTimeClient.ContainsKey(key))
                {
                    if (cacheTimeClient.RemoveEntry(key))
                    {
                        cacheTimeClient.SetEntry(key, cacheTime);
                    }
                }
                else
                {
                    cacheTimeClient.SetEntry(key, cacheTime);
                }
            }
        }

        public DateTime GetCacheTime(string hotelId)
        {
            string key = GetCacheKey("Time:" + hotelId);

            using (var client = pm.GetPooledClientManager(hotelId).GetClient())
            {
                var cacheTimeClient = client.GetTypedClient<RoomCacheTime>();

                if (cacheTimeClient.ContainsKey(key))
                {
                    return cacheTimeClient.GetValue(key).Timestamp;
                }
                
            }
            return GlobalCode.VALID_MIN_DATETIME;
        }
    }
}
